package com.neo.tiny.config;

import com.neo.tiny.componse.RestAuthenticationEntryPoint;
import com.neo.tiny.componse.RestfulAccessDeniedHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.filter.OncePerRequestFilter;

/**
 * @author yqz
 * @Description 基础安全配置
 * @CreateDate 2022/8/3 18:05
 */
public abstract class BaseSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private RestfulAccessDeniedHandler restfulAccessDeniedHandler;
    @Autowired
    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;

    /**
     * 获取白名单
     *
     * @return 白名单列表
     */
    public abstract String[] getWhiteUri();


    /**
     * 请求过滤器
     *
     * @return
     */
    public abstract OncePerRequestFilter getRequestFilter();


    /**
     * 允许基于选择匹配在资源级配置基于网络的安全性。
     * 以下示例将以/ admin /开头的网址限制为具有ADMIN角色的用户，并声明任何其他网址需要成功验证。
     * 也就是对角色的权限——所能访问的路径做出限制
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //首页所有人可以访问，功能只有对应权限的人才可以访问
        //请求授权的规则
        http.authorizeRequests()
                .antMatchers(getWhiteUri())
                .permitAll()
                //跨域请求会先进行一次options请求
                .antMatchers(HttpMethod.OPTIONS)
                .permitAll()
                // 除了以上路径，其他都需要验证
                .anyRequest()
                .authenticated();
        // 禁用缓存
        http.headers().cacheControl();
        //防止网站攻击：get post
        http.csrf().disable()//关闭csrf跨站攻击，登出失败可能的原因
                // 内嵌iframe
                .headers().frameOptions().disable();

        //基于token所以不需要session
        http.sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.addFilterBefore(getRequestFilter(), UsernamePasswordAuthenticationFilter.class);

        http.exceptionHandling()
                .accessDeniedHandler(restfulAccessDeniedHandler)
                .authenticationEntryPoint(restAuthenticationEntryPoint);

//        http.authorizeRequests()
//                .and()
//                .formLogin()
//                .and()
//                .httpBasic();

    }


    /**
     * SpringSecurity5.0以后，密码需要加密
     *
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    @Override
    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }
}
